/*
 * Copyright (C) 2011 Jason von Nieda <jason@vonnieda.org>
 * 
 * This file is part of OpenPnP.
 * 
 * OpenPnP is free software: you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * OpenPnP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with OpenPnP. If not, see
 * <http://www.gnu.org/licenses/>.
 * 
 * For more information about OpenPnP visit http://openpnp.org
 */

package org.openpnp.gui.components;

import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;

/**
 * Class that allows you to add a JSeparator to the ComboBoxModel.
 *
 * The separator is rendered as a horizontal line. Using the Up/Down arrow keys will cause the combo
 * box selection to skip over the separator. If you attempt to select the separator with the mouse,
 * the selection will be ignored and the drop down will remain open.
 */
@SuppressWarnings("serial")
public class SeparatorComboBox extends JComboBox implements KeyListener {
    // Track key presses and releases

    private boolean released = true;

    // Track when the separator has been selected
    private boolean separatorSelected = false;

    /**
     * Standard constructor. See JComboBox API for details
     */
    public SeparatorComboBox() {
        super();
        init();
    }

    /**
     * Standard constructor. See JComboBox API for details
     */
    public SeparatorComboBox(ComboBoxModel model) {
        super(model);
        init();
    }

    /**
     * Standard constructor. See JComboBox API for details
     */
    public SeparatorComboBox(Object[] items) {
        super(items);
        init();
    }

    /**
     * Standard constructor. See JComboBox API for details
     */
    public SeparatorComboBox(Vector<?> items) {
        super(items);
        init();
    }

    private void init() {
        setRenderer(new SeparatorRenderer());
        addKeyListener(this);
    }

    /**
     * Prevent selection of the separator by keyboard or mouse
     */
    @Override
    public void setSelectedIndex(int index) {
        Object value = getItemAt(index);

        // Attempting to select a separator

        if (value instanceof JSeparator) {
            // If no keys have been pressed then we must be using the mouse.
            // Prevent selection of the Separator when using the mouse

            if (released) {
                separatorSelected = true;
                return;
            }

            // Skip over the Separator when using the Up/Down keys

            int current = getSelectedIndex();
            index += (index > current) ? 1 : -1;

            if (index == -1 || index >= dataModel.getSize()) {
                return;
            }
        }

        super.setSelectedIndex(index);
    }

    /**
     * Prevent closing of the popup when attempting to select the separator with the mouse.
     */
    @Override
    public void setPopupVisible(boolean visible) {
        // Keep the popup open when the separator was clicked on

        if (separatorSelected) {
            separatorSelected = false;
            return;
        }

        super.setPopupVisible(visible);
    }

    //
    // Implement the KeyListener interface
    //
    public void keyPressed(KeyEvent e) {
        released = false;
    }

    public void keyReleased(KeyEvent e) {
        released = true;
    }

    public void keyTyped(KeyEvent e) {}

    /**
     * Class to render the JSeparator compenent
     */
    class SeparatorRenderer implements ListCellRenderer {
        private ListCellRenderer renderer;

        public SeparatorRenderer() {
            renderer = new JComboBox().getRenderer();
        }

        public Component getListCellRendererComponent(JList list, Object value, int index,
                boolean isSelected, boolean cellHasFocus) {
            if (value instanceof JSeparator) {
                return (JSeparator) value;
            }
            else {
                return renderer.getListCellRendererComponent(list, value, index, isSelected,
                        cellHasFocus);
            }
        }
    }
}
